Do not pickle vcpu state on save/restore. We can construct
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 3 Oct 2005 14:02:23 +0000 (15:02 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 3 Oct 2005 14:02:23 +0000 (15:02 +0100)
suitable initial state for each vcpu during restore, without
need for pickle/unpickle.

Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c

index d75dcd67a9f0b5bfb95d37a829f0ec59d585c781..38940bbea64703c706810bad25079671ca3cded8 100644 (file)
@@ -141,6 +141,13 @@ static inline void play_dead(void)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+void cpu_restore(void)
+{
+       play_dead();
+       local_irq_enable();
+       cpu_idle();
+}
+
 /*
  * The idle thread. There's no useful work to be
  * done, so just try to conserve power and have a
index dba898d0c367b9ab3b06934465bd9277edce994e..7fe4d8da07636638d51edbaaa1fe5a30a0e06e20 100644 (file)
@@ -802,7 +802,6 @@ static int __init do_boot_cpu(int apicid)
        extern void hypervisor_callback(void);
        extern void failsafe_callback(void);
        extern void smp_trap_init(trap_info_t *);
-       int i;
 
        cpu = ++cpucount;
        /*
@@ -853,12 +852,6 @@ static int __init do_boot_cpu(int apicid)
        /* FPU is set up to default initial state. */
        memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
 
-       /* Virtual IDT is empty at start-of-day. */
-       for ( i = 0; i < 256; i++ )
-       {
-               ctxt.trap_ctxt[i].vector = i;
-               ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
-       }
        smp_trap_init(ctxt.trap_ctxt);
 
        /* No LDT. */
@@ -1585,61 +1578,48 @@ void smp_resume(void)
        local_setup_timer_irq();
 }
 
-static atomic_t vcpus_rebooting;
-
-static void restore_vcpu_ready(void)
+void vcpu_prepare(int vcpu)
 {
+       extern void hypervisor_callback(void);
+       extern void failsafe_callback(void);
+       extern void smp_trap_init(trap_info_t *);
+       extern void cpu_restore(void);
+       vcpu_guest_context_t ctxt;
+       struct task_struct *idle = idle_task(vcpu);
 
-       atomic_dec(&vcpus_rebooting);
-}
+       if (vcpu == 0)
+               return;
 
-void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
-       int r;
-       int gdt_pages;
-       r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
-       if (r != 0)
-               panic("pickling vcpu %d -> %d!\n", vcpu, r);
-
-       /* Translate from machine to physical addresses where necessary,
-          so that they can be translated to our new machine address space
-          after resume.  libxc is responsible for doing this to vcpu0,
-          but we do it to the others. */
-       gdt_pages = (ctxt->gdt_ents + 511) / 512;
-       ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
-       for (r = 0; r < gdt_pages; r++)
-               ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
-}
+       memset(&ctxt, 0, sizeof(ctxt));
 
-int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
-       int r;
-       int gdt_pages = (ctxt->gdt_ents + 511) / 512;
-
-       /* This is kind of a hack, and implicitly relies on the fact that
-          the vcpu stops in a place where all of the call clobbered
-          registers are already dead. */
-       ctxt->user_regs.esp -= 4;
-       ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
-       ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready;
-
-       /* De-canonicalise.  libxc handles this for vcpu 0, but we need
-          to do it for the other vcpus. */
-       ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
-       for (r = 0; r < gdt_pages; r++)
-               ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
-
-       atomic_set(&vcpus_rebooting, 1);
-       r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
-       if (r != 0) {
-               printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
-               return -1;
-       }
+       ctxt.user_regs.ds = __USER_DS;
+       ctxt.user_regs.es = __USER_DS;
+       ctxt.user_regs.fs = 0;
+       ctxt.user_regs.gs = 0;
+       ctxt.user_regs.ss = __KERNEL_DS;
+       ctxt.user_regs.cs = __KERNEL_CS;
+       ctxt.user_regs.eip = (unsigned long)cpu_restore;
+       ctxt.user_regs.esp = idle->thread.esp;
+       ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1;
 
-       /* Make sure we wait for the new vcpu to come up before trying to do
-          anything with it or starting the next one. */
-       while (atomic_read(&vcpus_rebooting))
-               barrier();
+       memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
 
-       return 0;
+       smp_trap_init(ctxt.trap_ctxt);
+
+       ctxt.ldt_ents = 0;
+
+       ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address);
+       ctxt.gdt_ents      = cpu_gdt_descr[vcpu].size / 8;
+
+       ctxt.kernel_ss = __KERNEL_DS;
+       ctxt.kernel_sp = idle->thread.esp0;
+
+       ctxt.event_callback_cs     = __KERNEL_CS;
+       ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
+       ctxt.failsafe_callback_cs  = __KERNEL_CS;
+       ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
+
+       ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
+
+       (void)HYPERVISOR_boot_vcpu(vcpu, &ctxt);
 }
index 323e7409c9283521d56e6f056e368d9058c18cad..81f701b8a43765047513b184b13b714f11ee30c4 100644 (file)
@@ -1012,6 +1012,12 @@ void __init trap_init(void)
 void smp_trap_init(trap_info_t *trap_ctxt)
 {
        trap_info_t *t = trap_table;
+       int i;
+
+       for (i = 0; i < 256; i++) {
+               trap_ctxt[i].vector = i;
+               trap_ctxt[i].cs     = FLAT_KERNEL_CS;
+       }
 
        for (t = trap_table; t->address; t++) {
                trap_ctxt[t->vector].flags = t->flags;
index 5a093f679540b2064870d71fd1618e54283d97cb..59fc5f0b78f42c5663177c91239216c359c3c19a 100644 (file)
@@ -74,11 +74,8 @@ static int __do_suspend(void *ignore)
        extern unsigned long *pfn_to_mfn_frame_list[];
 
 #ifdef CONFIG_SMP
-       static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
-       cpumask_t prev_online_cpus, prev_present_cpus;
-
-       void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
-       int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
+       cpumask_t prev_online_cpus;
+       int vcpu_prepare(int vcpu);
 #endif
 
        extern void xencons_resume(void);
@@ -132,16 +129,6 @@ static int __do_suspend(void *ignore)
 
        preempt_enable();
 
-#ifdef CONFIG_SMP
-       cpus_clear(prev_present_cpus);
-       for_each_present_cpu(i) {
-               if (i == 0)
-                       continue;
-               save_vcpu_context(i, &suspended_cpu_records[i]);
-               cpu_set(i, prev_present_cpus);
-       }
-#endif
-
        gnttab_suspend();
 
 #ifdef __i386__
@@ -189,11 +176,6 @@ static int __do_suspend(void *ignore)
 
        time_resume();
 
-#ifdef CONFIG_SMP
-       for_each_cpu_mask(i, prev_present_cpus)
-               restore_vcpu_context(i, &suspended_cpu_records[i]);
-#endif
-
        __sti();
 
        xencons_resume();
@@ -201,6 +183,9 @@ static int __do_suspend(void *ignore)
        xenbus_resume();
 
 #ifdef CONFIG_SMP
+       for_each_present_cpu(i)
+               vcpu_prepare(i);
+
  out_reenable_cpus:
        for_each_cpu_mask(i, prev_online_cpus) {
                j = cpu_up(i);
index ee0ebd51c8385cc8c1631c0e242870b6e4bc93a7..a48b7aa4696b771699c27af5600f66dff85d6e19 100644 (file)
@@ -742,12 +742,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
        /* FPU is set up to default initial state. */
        memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
 
-       /* Virtual IDT is empty at start-of-day. */
-       for ( i = 0; i < 256; i++ )
-       {
-               ctxt.trap_ctxt[i].vector = i;
-               ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
-       }
        smp_trap_init(ctxt.trap_ctxt);
 
        /* No LDT. */
@@ -1267,13 +1261,8 @@ void smp_resume(void)
        local_setup_timer_irq();
 }
 
-void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
-}
-
-int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+void vcpu_prepare(int vcpu)
 {
-       return 0;
 }
 
 #endif
index 9008537635622377d429f638bbf2093bce128be0..fc4defe342f0625ff608bfe32f44ec718184eb61 100644 (file)
@@ -956,6 +956,12 @@ void __init trap_init(void)
 void smp_trap_init(trap_info_t *trap_ctxt)
 {
        trap_info_t *t = trap_table;
+       int i;
+
+       for (i = 0; i < 256; i++) {
+               trap_ctxt[i].vector = i;
+               trap_ctxt[i].cs     = FLAT_KERNEL_CS;
+       }
 
        for (t = trap_table; t->address; t++) {
                trap_ctxt[t->vector].flags = t->flags;